home *** CD-ROM | disk | FTP | other *** search
/ HaCKeRz Kr0nlcKLeZ 1 / HaCKeRz Kr0nlcKLeZ.iso / chibacity / gbbdisk.arj / BBS / FATMAN.ASM < prev    next >
Encoding:
Assembly Source File  |  1995-07-03  |  11.7 KB  |  285 lines

  1. ;12 Bit File Attribute Table manipulation routines. These routines only
  2. ;require a one sector buffer for the FAT, no matter how big it is.
  3.  
  4. ;The following data area must be in this order. It is an image of the data
  5. ;stored in the boot sector.
  6. MAX_CLUST       DW      ?               ;maximum cluster number
  7. SECS_PER_CLUST  DB      ?               ;sectors per cluster
  8. RESERVED_SECS   DW      ?               ;reserved sectors at beginning of disk
  9. FATS            DB      ?               ;copies of fat on disk
  10. DIR_ENTRIES     DW      ?               ;number of entries in root directory
  11. SECTORS_ON_DISK DW      ?               ;total number of sectors on disk
  12. FORMAT_ID       DB      ?               ;disk format ID
  13. SECS_PER_FAT    DW      ?               ;number of sectors per FAT
  14. SECS_PER_TRACK  DW      ?               ;number of sectors per track (one head)
  15. HEADS           DW      ?               ;number of heads on disk
  16.  
  17. ;The following data is not in the boot sector. It is initialized by INIT_FAT_MANAGER.
  18. CURR_FAT_SEC    DB      ?               ;current fat sector in memory 0=not there
  19.  
  20. ;The following must be set prior to calling INIT_FAT_MANAGER or using any of
  21. ;these routines.
  22. CURR_DISK       DB      ?               ;current disk drive
  23.  
  24. ;This routine is passed the number of contiguous free sectors desired in bx,
  25. ;and it attempts to locate them on the disk. If it can, it returns the FAT
  26. ;entry number in cx, and the C flag reset. If there aren't that many contiguous
  27. ;free sectors available, it returns with C set.
  28. FIND_FREE:
  29.         mov     al,[SECS_PER_CLUST]
  30.         xor     ah,ah
  31.         xchg    ax,bx
  32.         xor     dx,dx
  33.         div     bx                      ;ax=clusters requested, may have to increment
  34.         or      dx,dx
  35.         jz      FF1
  36.         inc     ax                      ;adjust for odd number of sectors
  37. FF1:    mov     bx,ax                   ;clusters requested in bx now
  38.         xor     dx,dx                   ;this is the contiguous free sector counter
  39.         mov     [CURR_FAT_SEC],dl       ;initialize this subsystem
  40.         mov     cx,2                    ;this is the cluster index, start at 2
  41. FFL1:   push    bx
  42.         push    cx
  43.         push    dx
  44.         call    GET_FAT_ENTRY           ;get FAT entry cx's value in ax
  45.         pop     dx
  46.         pop     cx
  47.         pop     bx
  48.         or      ax,ax                   ;is entry zero?
  49.         jnz     FFL2                    ;no, go reset sector counter
  50.         add     dl,[SECS_PER_CLUST]     ;else increment sector counter
  51.         adc     dh,0
  52.         jmp     SHORT FFL3
  53. FFL2:   xor     dx,dx                   ;reset sector counter to zero
  54. FFL3:   cmp     dx,bx                   ;do we have enough sectors now?
  55.         jnc     FFL4                    ;yes, finish up
  56.         inc     cx                      ;else check another cluster
  57.         cmp     cx,[MAX_CLUST]          ;unless we're at the maximum allowed
  58.         jnz     FFL1                    ;not max, do another
  59. FFL4:   cmp     dx,bx                   ;do we have enough sectors
  60.         jc      FFEX                    ;no, exit with C flag set
  61. FFL5:   mov     al,[SECS_PER_CLUST]     ;yes, now adjust cx to point to start
  62.         xor     ah,ah
  63.         sub     dx,ax
  64.         dec     cx
  65.         or      dx,dx
  66.         jnz     FFL5
  67.         inc     cx                      ;cx points to first free cluster in block now
  68.         clc                             ;clear carry flag to indicate success
  69. FFEX:   ret
  70.  
  71. ;This routine marks cx sectors as bad, starting at cluster dx. It does so
  72. ;only with the FAT sector currently in memory, and the marking is done only in
  73. ;memory. The FAT must be written to disk using UPDATE_FAT_SECTOR to make
  74. ;the marking effective.
  75. MARK_CLUSTERS:
  76.         push    dx
  77.         mov     al,[SECS_PER_CLUST]
  78.         xor     ah,ah
  79.         xchg    ax,cx
  80.         xor     dx,dx
  81.         div     cx                      ;ax=clusters requested, may have to increment
  82.         or      dx,dx
  83.         jz      MC1
  84.         inc     ax                      ;adjust for odd number of sectors
  85. MC1:    mov     cx,ax                   ;clusters requested in bx now
  86.         pop     dx
  87. MC2:    push    cx
  88.         push    dx
  89.         call    MARK_CLUST_BAD          ;mark FAT cluster requested bad
  90.         pop     dx
  91.         pop     cx
  92.         inc     dx
  93.         loop    MC2
  94.         ret
  95.  
  96. ;This routine marks the single cluster specified in dx as bad. Marking is done
  97. ;only in memory. It assumes the proper sector is loaded in memory. It will not
  98. ;work properly to mark a cluster which crosses a sector boundary in the FAT.
  99. MARK_CLUST_BAD:
  100.         push    dx
  101.         mov     cx,dx
  102.         call    GET_FAT_OFFSET          ;put FAT offset in bx
  103.         mov     ax,bx
  104.         mov     si,OFFSET SCRATCHBUF    ;point to disk buffer
  105.         and     bx,1FFH                 ;get offset in currently loaded sector
  106.         pop     cx                      ;get fat sector number now
  107.         mov     al,cl                   ;see if even or odd
  108.         shr     al,1                    ;put low bit in c flag
  109.         mov     ax,[bx+si]              ;get fat entry before branching
  110.         jc      MCBO                    ;odd, go handle that case
  111. MCBE:   and     ax,0F000H               ;for even entries, just modify low 12 bits
  112.         or      ax,0FF7H
  113. MCBF:   cmp     bx,511                  ;if offset is 511, we cross a sector boundary
  114.         jz      MCBEX                   ;so go handle it specially
  115.         mov     [bx+si],ax
  116. MCBEX:  ret
  117.  
  118. MCBO:   and     ax,0000FH               ;for odd, modify upper 12 bits
  119.         or      ax,0FF70H
  120.         jmp     SHORT MCBF
  121.  
  122.  
  123. ;This routine gets the value of the FAT entry number cx and returns it in ax.
  124. GET_FAT_ENTRY:
  125.         push    cx
  126.         call    GET_FAT_OFFSET          ;put FAT offset in bx
  127.         mov     ax,bx
  128.         mov     cl,9                    ;determine which sector of the FAT is needed
  129.         shr     ax,cl
  130.         inc     ax                      ;sector # now in al (1=first)
  131.         cmp     al,[CURR_FAT_SEC]       ;is this the currently loaded FAT sector?
  132.         jz      FATLD                   ;yes, go get the value
  133.         push    bx                      ;no, load new sector first
  134.         call    GET_FAT_SECTOR
  135.         pop     bx
  136. FATLD:  mov     si,OFFSET SCRATCHBUF    ;point to disk buffer
  137.         and     bx,1FFH                 ;get offset in currently loaded sector
  138.         pop     cx                      ;get fat sector number now
  139.         mov     al,cl                   ;see if even or odd
  140.         shr     al,1                    ;put low bit in c flag
  141.         mov     ax,[bx+si]              ;get fat entry before branching
  142.         jnc     GFEE                    ;odd, go handle that case
  143. GFEO:   mov     cl,4                    ;for odd entries, shift right 4 bits first
  144.         shr     ax,cl                   ;and move them down
  145. GFEE:   and     ax,0FFFH                ;for even entries, just AND low 12 bits
  146.         cmp     bx,511                  ;if offset is 511, we cross a sector boundary
  147.         jnz     GFSBR                   ;if not exit,
  148.         mov     ax,0FFFH                ;else fake as if it is occupied
  149. GFSBR:  ret
  150.  
  151. ;This routine reads the FAT sector number requested in al. The first is 1,
  152. ;second is 2, etc. It updates the CURR_FAT_SEC variable once the sector has
  153. ;been successfully loaded.
  154. GET_FAT_SECTOR:
  155.         inc     ax                      ;increment al to get sector number on track 0
  156.         mov     cl,al
  157. GFSR:   mov     ch,0
  158.         mov     dl,[CURR_DISK]
  159.         mov     dh,0
  160.         mov     bx,OFFSET SCRATCHBUF
  161.         mov     ax,0201H                ;read FAT sector into buffer
  162.         int     40H
  163.         jc      GFSR                    ;retry if an error
  164.         dec     cx
  165.         mov     [CURR_FAT_SEC],cl
  166.         ret
  167.  
  168. ;This routine gets the byte offset of the FAT entry CX and puts it in BX.
  169. ;It works for any 12-bit FAT table.
  170. GET_FAT_OFFSET:
  171.         mov     ax,3                    ;multiply by 3
  172.         mul     cx
  173.         shr     ax,1                    ;divide by 2
  174.         mov     bx,ax
  175.         ret
  176.  
  177.  
  178. ;This routine converts the cluster number into an absolute Trk,Sec,Hd number.
  179. ;The cluster number is passed in cx, and the Trk,Sec,Hd are returned in
  180. ;cx and dx in INT 13H style format.
  181. CLUST_TO_ABSOLUTE:
  182.         dec     cx
  183.         dec     cx                      ;clusters-2
  184.         mov     al,[SECS_PER_CLUST]
  185.         xor     ah,ah
  186.         mul     cx                      ;ax=(clusters-2)*(secs per clust)
  187.         push    ax
  188.         mov     ax,[DIR_ENTRIES]
  189.         xor     dx,dx
  190.         mov     cx,16
  191.         div     cx
  192.         pop     cx
  193.         add     ax,cx                   ;ax=(dir entries)/16+(clusters-2)*(secs per clust)
  194.         push    ax
  195.         mov     al,[FATS]
  196.         xor     ah,ah
  197.         mov     cx,[SECS_PER_FAT]
  198.         mul     cx                      ;ax=fats*secs per fat
  199.         pop     cx
  200.         add     ax,cx
  201.         add     ax,[RESERVED_SECS]      ;ax=absolute sector # now (0=boot sector)
  202.         mov     bx,ax
  203.         mov     cx,[SECS_PER_TRACK]
  204.         mov     ax,[HEADS]
  205.         mul     cx
  206.         mov     cx,ax
  207.         xor     dx,dx
  208.         mov     ax,bx
  209.         div     cx                      ;ax=(abs sec #)/(heads*secs per trk)=trk
  210.         push    ax
  211.         mov     ax,dx                   ;remainder to ax
  212.         mov     cx,[SECS_PER_TRACK]
  213.         xor     dx,dx
  214.         div     cx
  215.         mov     dh,al                   ;dh=head #
  216.         mov     cl,dl
  217.         inc     cx                      ;cl=sector #
  218.         pop     ax
  219.         mov     ch,al                   ;ch=track #
  220.         ret
  221.  
  222.  
  223. ;This routine updates the FAT sector currently in memory to disk. It writes
  224. ;both FATs using INT 13.
  225. UPDATE_FAT_SECTOR:
  226.         mov     cx,[RESERVED_SECS]
  227.         add     cl,[CURR_FAT_SEC]
  228.         xor     dh,dh
  229.         mov     dl,[CURR_DISK]
  230.         mov     bx,OFFSET SCRATCHBUF
  231.         mov     ax,0301H
  232.         int     40H                             ;update first FAT
  233.         add     cx,[SECS_PER_FAT]
  234.         cmp     cx,[SECS_PER_TRACK]             ;need to go to head 1?
  235.         jbe     UFS1
  236.         sub     cx,[SECS_PER_TRACK]
  237.         inc     dh
  238. UFS1:   mov     ax,0301H
  239.         int     40H                             ;update second FAT
  240.         ret
  241.  
  242. ;This routine initializes the disk variables necessary to use the fat managment
  243. ;routines
  244. INIT_FAT_MANAGER:
  245.         push    ax
  246.         push    bx
  247.         push    cx
  248.         push    dx
  249.         push    si
  250.         push    di
  251.         push    ds
  252.         push    es
  253.         mov     ax,cs
  254.         mov     ds,ax
  255.         mov     es,ax
  256.         mov     cx,15
  257.         mov     si,OFFSET SCRATCHBUF+13
  258.         mov     di,OFFSET SECS_PER_CLUST
  259.         rep     movsb                           ;move data from boot sector
  260.         mov     [CURR_FAT_SEC],0                ;initialize this
  261.         mov     ax,[SECTORS_ON_DISK]            ;total sectors on disk
  262.         mov     bx,[DIR_ENTRIES]
  263.         mov     cl,4
  264.         shr     bx,cl
  265.         sub     ax,bx                           ;subtract size of root dir
  266.         mov     bx,[SECS_PER_FAT]
  267.         shl     bx,1
  268.         sub     ax,bx                           ;subtract size of fats
  269.         dec     ax                              ;subtract boot sector
  270.         xor     dx,dx
  271.         mov     bl,[SECS_PER_CLUST]             ;divide by sectors per cluster
  272.         xor     bh,bh
  273.         div     bx
  274.         inc     ax                              ;and add 1 so ax=max cluster
  275.         mov     [MAX_CLUST],ax
  276.         pop     es
  277.         pop     ds
  278.         pop     di
  279.         pop     si
  280.         pop     dx
  281.         pop     cx
  282.         pop     bx
  283.         pop     ax
  284.         ret
  285.